#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2023/5/5 11:19
# @Author : 闫峰
# @File    : regular_control.py
import re
import random
from datetime import date, timedelta
from faker import Faker
from utils.logging_tool.log_control import ERROR
import datetime
import hashlib
import hmac
import json
import time
from datetime import datetime, timezone
from hashlib import sha256
import binascii


class Context:
    """ 正则替换 """

    def __init__(self):
        self.faker = Faker(locale='zh_CN')

    @classmethod
    def random_int(cls) -> int:
        """
        :return: 随机数
        """
        _data = random.randint(0, 5000)
        return _data

    def get_phone(self) -> int:
        """
        :return: 随机生成手机号码
        """
        phone = self.faker.phone_number()
        return phone

    def get_id_number(self) -> int:
        """

        :return: 随机生成身份证号码
        """

        id_number = self.faker.ssn()
        return id_number

    def get_female_name(self) -> str:
        """

        :return: 女生姓名
        """
        female_name = self.faker.name_female()
        return female_name

    def get_male_name(self) -> str:
        """

        :return: 男生姓名
        """
        male_name = self.faker.name_male()
        return male_name

    def get_email(self) -> str:
        """

        :return: 生成邮箱
        """
        email = self.faker.email()
        return email

    def get_trace_id(self):
        return "flow_" + Context.genere_timestamp()

    @classmethod
    def self_operated_id(cls):
        """自营店铺 ID """
        operated_id = 212
        return operated_id

    @classmethod
    def get_time(cls) -> str:
        """
        计算当前时间
        :return:
        """
        now_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        return now_time

    @classmethod
    def today_date(cls):
        """获取今日0点整时间"""

        _today = date.today().strftime("%Y-%m-%d") + " 00:00:00"
        return str(_today)

    @classmethod
    def time_after_week(cls):
        """获取一周后12点整的时间"""

        _time_after_week = (date.today() + timedelta(days=+6)).strftime("%Y-%m-%d") + " 00:00:00"
        return _time_after_week

    @classmethod
    def host(cls) -> str:
        from utils import config
        """ 获取接口域名 """
        return config.host

    @classmethod
    def get_time_by_days(cls, days: int):
        # 当前时间
        now = datetime.datetime.now()

        # 加减天数
        delta = datetime.timedelta(days=days)  # 4年
        new_date = now + delta

        # 生成字符串
        new_date_str = new_date.strftime('%Y-%m-%d %H:%M:%S')

        # print(new_date_str)  # 输出：2023-08-19 00:00:00
        return new_date_str

    @classmethod
    def get_time_by_daysutc(cls, days: int):
        # 当前时间
        now = datetime.datetime.now()

        # 加减天数
        delta = datetime.timedelta(days=days)  # 4年
        new_date = now + delta

        # 生成字符串
        new_date_str = new_date.strftime('%Y-%m-%dT%H:%M:%S.000Z')

        # print(new_date_str)  # 输出：2023-08-19T00:00:00.000Z
        return new_date_str

    @classmethod
    def get_time_by_days(cls, days: int):
        # 当前时间
        now = datetime.datetime.now()

        # 加减天数
        delta = datetime.timedelta(days=days)  # 4年
        new_date = now + delta

        # 生成字符串
        new_date_str = new_date.strftime('%Y-%m-%d %H:%M:%S')

        # print(new_date_str)  # 输出：2023-08-19 00:00:00
        return new_date_str

    @staticmethod
    def genere_timestamp():
        TS = time.time()
        str_TS = str(TS)
        return str_TS[0:10]
    @staticmethod
    def get_payload_self_arm():
        data = {
                        "IDC": "cn-north-neimeng-3000",
                        "Amount": 3,
                        "Spec": "egc-armg-v3",
                        "SystemImageID": "cimg-7KN90HlxTqK_YS2i343i_30",
                   }
        return str(data)

    @staticmethod
    def get_sign(action, payload:str,sk):
        now = datetime.now(timezone.utc)
        hash_value = Context.sha256_hash(getattr(Context(),payload)())
        canonicalRequest = "POST" + "\n" + action + "\n" + hash_value
        hashedCanonicalRequest = Context.sha256_hash(canonicalRequest)
        Date = now.strftime('%Y-%m-%d')
        string2sign = Context.genere_timestamp() + "\n" + Date + "/yt_request" + "\n" + hashedCanonicalRequest
        SecretDate = Context.hmac_sha256(Date, ("YT" + sk).encode('utf-8'))
        SecretSigning = Context.hmac_sha256("yt_request", SecretDate)
        signature = Context.hmac_sha256(string2sign, SecretSigning)
        signature_end = Context.hex_encode_to_string(signature)
        return signature_end

    @staticmethod
    def sha256_hash(message):
        sha256 = hashlib.sha256()
        sha256.update(message.encode('utf-8'))
        hash_value = sha256.hexdigest()
        return hash_value

    @staticmethod
    def hmac_sha256(s, key):
        s = s.encode('utf-8')
        sign = hmac.new(key, s, digestmod=sha256).digest()
        return sign

    @staticmethod
    def hex_encode_to_string(byte_string):
        return binascii.hexlify(byte_string).decode('utf-8')



def regular(target):
    """
    新版本
    使用正则替换请求数据
    :return:
    """
    try:
        regular_pattern = r'\${{(.*?)}}'
        while re.findall(regular_pattern, target):
            key = re.search(regular_pattern, target).group(1)
            value_types = ['int:', 'bool:', 'list:', 'dict:', 'tuple:', 'float:']
            if any(i in key for i in value_types) is True:
                func_name = key.split(":")[1].split("(")[0]
                value_name = key.split(":")[1].split("(")[1][:-1]
                if value_name == "":
                    value_data = getattr(Context(), func_name)()
                else:
                    value_data = getattr(Context(), func_name)(*value_name.split(","))
                regular_int_pattern = r'\'\${{(.*?)}}\''
                target = re.sub(regular_int_pattern, str(value_data), target, 1)
            else:
                func_name = key.split("(")[0]
                value_name = key.split("(")[1][:-1]
                if value_name == "":
                    value_data = getattr(Context(), func_name)()
                else:
                    value_data = getattr(Context(), func_name)(*value_name.split(","))
                target = re.sub(regular_pattern, str(value_data), target, 1)
        return target

    except AttributeError:
        ERROR.logger.error("未找到对应的替换的数据, 请检查数据是否正确 %s", target)
        raise
    except IndexError:
        ERROR.logger.error("yaml中的 ${{}} 函数方法不正确，正确语法实例：${{get_time()}}")
        raise


def cache_regular(value):
    from utils.cache_process.cache_control import CacheHandler

    """
    通过正则的方式，读取缓存中的内容
    例：$cache{login_init}
    :param value:
    :return:
    """
    # 正则获取 $cache{login_init}中的值 --> login_init
    regular_dates = re.findall(r"\$cache\{(.*?)\}", value)

    # 拿到的是一个list，循环数据
    for regular_data in regular_dates:
        value_types = ['int:', 'bool:', 'list:', 'dict:', 'tuple:', 'float:']
        if any(i in regular_data for i in value_types) is True:
            value_types = regular_data.split(":")[0]
            regular_data = regular_data.split(":")[1]
            # pattern = re.compile(r'\'\$cache{' + value_types.split(":")[0] + r'(.*?)}\'')
            pattern = re.compile(r'\"\$cache\{' + value_types.split(":")[0] + ":" + regular_data + r'\}\"')
        else:
            pattern = re.compile(
                r'\$cache\{' + regular_data.replace('$', "\$").replace('[', '\[') + r'\}'
            )
        try:
            # cache_data = Cache(regular_data).get_cache()
            cache_data = CacheHandler.get_cache(regular_data)
            if not cache_data:
                cache_data = "缓存中无数据"
            # 使用sub方法，替换已经拿到的内容
            value = re.sub(pattern, str(cache_data), value)
        except Exception:
            pass
    return value


def build_param(value):
    is_str = False
    if not isinstance(value, str):
        value = json.dumps(value)
        value = cache_regular(value)
    else:
        value = cache_regular(value)
        is_str = True
    if not is_str:
        value = value.replace('null', 'None')
        value = value.replace('true', 'True')
        value = eval(value)
    return value


def build_param1(_string):
    '''
    识别${key}并替换成全局变量池的value,处理___func()函数助手
    :param _string:
    :param str: 待替换的字符串
    :return:
    '''
    # 识别${key}的正则表达式
    EXPR = r'\$\{(.*?)\}'
    # 识别函数助手
    FUNC_EXPR = r'___.+?\(.*?\)'
    is_str = 0
    # 遍历所有取值并做替换
    if not isinstance(_string, str):
        _string = json.dumps(_string)
    else:
        is_str = 1
    _string = cache_regular(_string)
    # print()
    # keys = re.findall(EXPR, _string)
    # for key in keys:
    #     # value = self.saves.get(key)
    #     value = CacheHandler.get_cache(key)
    #     # pattern = re.compile(r'\'\$\{' + key+ r'\}\'')
    #     #
    #     # _string = re.sub(pattern, str(value), _string)
    #     _string = _string.replace('\"${' + key + '}\"', str(value))

    # 遍历所有函数助手并执行，结束后替换
    funcs = re.findall(FUNC_EXPR, _string)
    for func in funcs:
        fuc = func.split('___')[1]
        fuc_name = fuc.split("(")[0]
        fuc = fuc.replace(fuc_name, fuc_name.lower())
        value = eval(fuc)
        _string = _string.replace(func, str(value))
    # if 'false' in _string:
    #     _string = _string.replace("false", "False")
    # if 'true' in _string:
    #     _string = _string.replace("true", "True")
    if is_str:
        return _string
    else:
        return json.loads(_string)


if __name__ == '__main__':
    a ="get_payload_self_arm"
    print(getattr(Context(), a))
    # pattern = re.compile(r'\"\$cache\{' + 'list:g_instance_id_list' + r'\}\"')
    # cache_data = [{'g_instance_id_list': 'ins-3lzqmob9anplvng5mz6zbzm8ubyhb0b6'},
    #               {'g_instance_id_list': 'ins-wvknlzkmfs1fyaq6d7ap9fr1vyk18diz'},
    #               {'g_instance_id_list': 'ins-u648kjtckomalr1tyogfr1vdu36ho334'}]
    # str1 = '[{"expressionType": "json", "path": "$.ret.code", "type": "==", "value": 0, "AssertType": null}, {"expressionType": "json", "path": "$.body.instances[*].gInstanceId", "type": "==", "value": "$cache{list:g_instance_id_list}", "AssertType": null}]'
    # value1 = re.sub(pattern, str(cache_data), str1)
    # print(value1)
